#include <ne.h>
#include <graphics/MD2Model.h>
#include <graphics/MD2ModelLoader.h>
#include <system/GlutApplication.h>

int    Width;               /* Width of window */
int    Height;              /* Height of window */
ne::Engine *pEngine = 0;
ne::MD2ModelLoader *modelLoaderP;
ne::MD2Model *modelP;
ne::TexturePtr tex;
uint32_t frame = 0;
float frameNum = 0;
float rotate = 0;

void keyboard(unsigned char key, int x, int y);
void redraw(void);
void resize(int width, int height);
void init();

int main(int argc, char *argv[]) /* I - Command-line arguments */
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(400, 400);
    glutCreateWindow("WYX MD2");
    glutReshapeFunc(resize);
    glutDisplayFunc(redraw);
    glutKeyboardFunc(keyboard);
    //glutFullScreen();
    pEngine = new ne::Engine();

    init();
    glutMainLoop();

    delete modelP;
    delete pEngine;
    return 0;
}

void init()
{
    modelLoaderP = new ne::MD2ModelLoader();
    modelP = modelLoaderP->loadModel("../model/tris.md2");
    delete modelLoaderP;
    //modelP->setPosition(ne::Vector3(0, 0, -100));

    glClearColor(0, 0, 0, 0);
    glClearDepth(1);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glFrontFace(GL_CCW);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);

    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);

    //glEnable(GL_LIGHTING);
    //glEnable(GL_LIGHT0);

    glShadeModel(GL_SMOOTH);

    tex = pEngine->getTextureManager()->createTextureFromFile("tex", "../image/texture.png", ne::TF_RGB);
    tex->load();
    tex->createRenderTexture();
}

void keyboard(unsigned char key, int x, int y)
{
    if (key == 'u' || key == 'U')
    {
    }
    else if (key == 'j' || key == 'J')
    {
    }
    else if (key == 'a' || key == 'A')
    {
        rotate -= 10;
    }
    else if (key == 'd' || key == 'D')
    {
        rotate += 10;
    }
    else if (key == 0x1b)
    {
        exit(0);
    }
}

void redraw(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    frameNum += 0.25;
    if (frameNum > modelP->getFrameNum()-1)
    {
        frameNum = 0;
    }
    frame = int(frameNum);
    int vertexNum = modelP->getFrameSize();
    ne::Vector3 pos(0, 0, -100);// = modelP->getPosition();
    glPushMatrix();
        glTranslatef(pos[0], pos[1], pos[2]);
        glRotatef(rotate, 0, 1, 0);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, tex->getSource());
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glBegin(GL_TRIANGLES);
            ne::MD2Model::IndexList *indexVP = modelP->getVertexIndexList();
            ne::MD2Model::IndexList *indexTP = modelP->getTexCoordIndexList();
            ne::MD2Model::VertexList *vertexList = modelP->getVertexList();
            ne::MD2Model::TexCoordList *texCoordList = modelP->getTexCoordList();
            for (uint32_t i=0; i<modelP->getTriangleAmount(); ++i)
            {
                for (uint32_t j=0; j<3; ++j)
                {
                    glTexCoord2fv((*texCoordList)[(*indexTP)[3*i+j]].ptr());
                    glVertex3fv((*vertexList)[frame * vertexNum + (*indexVP)[3*i+j]].ptr());
                }
            }
        glEnd();
        glDisable(GL_TEXTURE_2D);

        /*
        ne::MD2Model::VertexList *vertexList = modelP->getVertexList();
        glVertexPointer(3, GL_FLOAT, 0, &(*vertexList)[frame * vertexNum]);
        glEnableClientState(GL_VERTEX_ARRAY);
        ne::MD2Model::TexCoordList *texCoordList = modelP->getTexCoordList();
        glTexCoordPointer(2, GL_FLOAT, 0, &(*texCoordList)[0]);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        ne::MD2Model::IndexList *indexVP = modelP->getVertexIndexList();
        glDrawElements(GL_TRIANGLES, (*indexVP).size(), GL_UNSIGNED_INT, &(*indexVP)[0]);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        */
    glPopMatrix();
    glutSwapBuffers();
    glutPostRedisplay();
}

void resize(int width, int height)
{
    /* Save the new width and height */
    Width  = width;
    Height = height;

    /* Reset the viewport... */
    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, double(width)/double(height), 0.1, 10000.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

